package stockin

import (
	"context"
	"fmt"
	"golang.org/x/sync/errgroup"
	"net/http"
	"sync"
	"wms/model"

	"wms/internal/svc"
	"wms/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type StockinAddLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewStockinAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StockinAddLogic {
	return &StockinAddLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *StockinAddLogic) StockinAdd(req *types.StockInAddRequest) (resp *types.BaseResponse, err error) {
	resp = new(types.BaseResponse)

	//1.供货商是否存在
	supplier, err := l.svcCtx.SupplierModel.FindOne(l.ctx, req.SupplierId)
	switch err {
	case nil:
	case model.ErrNotFound:
		resp.Code = http.StatusBadRequest
		resp.Msg = "供货商不存在"
		return resp, nil
	default:
		resp.Code = http.StatusInternalServerError
		resp.Msg = "服务内部错误"
		return resp, nil
	}

	//2.原料类型是否存在
	var mux sync.RWMutex
	var g errgroup.Group
	var materials = make(map[int64]model.Materials)
	for _, detail := range req.List {
		item := detail
		g.Go(func() error {
			m, e := l.svcCtx.MaterialsModel.FindOne(l.ctx, item.MaterialsId)
			if e != nil {
				fmt.Printf("[Error]查询原料类型[%d]:%s\n", item.MaterialsId, e.Error())
			}
			mux.Lock()
			materials[item.MaterialsId] = *m
			mux.Unlock()
			return e
		})
	}

	if err = g.Wait(); err != nil {
		switch err {
		case nil:
		case model.ErrNotFound:
			resp.Code = http.StatusBadRequest
			resp.Msg = "部分原料类型不存在"
			return resp, nil
		default:
			resp.Code = http.StatusInternalServerError
			resp.Msg = "服务内部错误"
			return resp, nil
		}
	}

	//2.计算总金额
	if len(req.List) == 0 {
		resp.Code = http.StatusBadRequest
		resp.Msg = "请添加入库原料"
		return resp, nil
	}
	var total float64
	for _, material := range req.List {
		//单价（元）*数量（吨）
		total += material.Price * material.Weight
	}

	//3.写入stock_in表
	var tax int64
	var date int64
	if req.Status == 2 {
		date = req.Date
	}

	if req.HasTax {
		tax = req.Tax
	}
	res, err := l.svcCtx.StockInModel.Insert(l.ctx, &model.StockIn{
		SupplierId:    req.SupplierId,
		SupplierName:  supplier.Name,
		HasTax:        req.HasTax,
		Tax:           tax,
		Status:        req.Status,
		BalanceStatus: req.BalanceStatus,
		Date:          date,
		Total:         total,
		Deposit:       req.Deposit,
	})
	if err != nil {
		fmt.Printf("[Error]添加入库单:%s\n", err.Error())
		resp.Code = http.StatusInternalServerError
		resp.Msg = "服务内部错误"
		return resp, nil
	}

	//4.写入stock_in_detail表
	stockinId, err := res.LastInsertId()
	if err != nil {
		fmt.Printf("[Error]获取stock_id报错:%s\n", err.Error())
		resp.Code = http.StatusInternalServerError
		resp.Msg = "服务内部错误"
		return resp, nil
	}

	for _, detail := range req.List {
		_, err = l.svcCtx.StockInDetailModel.Insert(l.ctx, &model.StockInDetail{
			StockId:        stockinId,
			MaterialsId:    detail.MaterialsId,
			MaterialsName:  materials[detail.MaterialsId].Name,
			MaterialsTypes: materials[detail.MaterialsId].Types,
			Weight:         detail.Weight,
			Price:          detail.Price,
		})
		if err != nil {
			fmt.Printf("[Error]入库详情:%s\n", err.Error())
			resp.Code = http.StatusInternalServerError
			resp.Msg = "服务内部错误"
			return resp, nil
		}
	}

	resp.Code = http.StatusOK
	resp.Msg = "成功"
	return resp, nil
}
